#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <iostream>
#include <string>

using namespace std;

/*This handler bails us out after 5 seconds */

static void alarm_handler (int signo)
{
    exit (0);
}

/* Start of program execution */

int main()
{
/* Define the variables we will be using. The contents of the
broadcast_packet variable are based on the contents of a
packet captured using a packet sniffer (wireshark). The data
is exactly 25 bytes in size. The response is usually 114~ bytes,
but we'll use a larger buffer just to play safe.
*/
    int sockfd;
    const int on = 1;
    struct sockaddr_in address;
    struct sockaddr preply_addr;
    int result;
    char *broadcast_packet = "\xFF\xFF\xFF\xFFTSource Engine Query\xFF";
    char response[300];
    int addr_len = sizeof(preply_addr);
    int recvlen;
/* Initialise the socket for sending out a broadcast.
SOCK_DGRAM indicates a datagram protocol, or UDP.
We would use SOCK_STREAM for TCP.
*/
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = inet_addr("10.0.255.255");
    address.sin_port = htons(27015);
/* Clarify that we really want to do a broadcast and that this isn't
a mistake. The socket system makes this necessary just in case
we're a program that takes an IP address at the command line and
the user fooled us into making a broadcast.
*/
    setsockopt (sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
/* Broadcast now. Any CS servers that receive this will reply
with a 114~ byte UDP packet.
*/
result = sendto (sockfd, (void *) broadcast_packet, 25, 0,
(struct sockaddr *) &address, sizeof(address));
/* Abort with an error message if the broadcast didn't work */
    if (result == -1) {
	perror ("cscan");
	exit(1);
    }
/* Setup the handler that will bail us out after the timeout */
    signal (SIGALRM, alarm_handler);
/* Tell the system to raise the ALRM signal after 5 seconds */
    alarm (10);
/* Loop continously listening for responses to the broadcast from
any servers on the local network. The ALRM signal at the end of
5 seconds will bail us out.
*/
//	cout<<"yesssssssss";
    for (;;)
    {
/* recvfrom is a blocking call for UDP data. We need to listen on the
same port that we broadcasted from, hence the "sockfd" from the
original broadcast. */
//recvlen = recvfrom (sockfd, response, sizeof (response),0,&preply_addr, (socklen_t*)&addr_len);
//cout<<recvlen<<" recvlen";
        if ((recvlen = recvfrom (sockfd, response, sizeof (response), 0,&preply_addr, (socklen_t*)&addr_len)) > 0)
	{ 
	    cout<<"YESSSS\n";
/* We got a reply. This bit of code patches the packet contents
slightly to create printable text. Use a packet sniffer if you
want to see what the packet really contains. tcpdump won't work
here -- it loses the last few bytes. Try ethereal instead.
*/
	    response[recvlen-1] = '\0';
	    string resp;
	    resp=response;
   	//    resp.erase(0,5);
	    int check=0,i=0,j=0,k=0;
	    char ip[100],map_type[20],server_name[20];
	    for(int p=5;p<recvlen;p++)
	    {
		if(response[p]==0)
		{
			check++;
		
	//		cout<<response[p]<<"\n";
		}
		else
		{
			
			switch(check)
			{
				case 0:
				{
				        ip[i++]=response[p];
					break;
				}
				case 1:
				{
					server_name[k++]=response[p];
					break;
				}
				case 2:
				{
					map_type[j++]=response[p];
					break;
				}
				default:
				{
					break;
				}	
			}
		  }
	    }
	    for(int z=0;z<i;z++)
	    {
		cout<<ip[z];
	    }
	    cout<<endl;
	    for(int z=0;z<k;z++)
            {
                cout<<server_name[z];
            }
            cout<<endl;
	    for(int z=0;z<i+1;z++)
            {
                cout<<map_type[z];
            }
            cout<<endl;
	    
	    cout<<resp;
	}
    }
/* Execution never reaches here. Program termination is handled by the
alarm_handler function.
*/
}
